The following is your first chunk to start with. Remember, you can add chunks using the menu above (Insert -> R) or using the keyboard shortcut Ctrl+Alt+I. A good practice is to use different code chunks to answer different questions. You can delete this comment if you like.

Other useful keyboard shortcuts include Alt- for the assignment operator, and Ctrl+Shift+M for the pipe operator. You can delete these reminders if you don’t want them in your report.

library("CARS")
library("lubridate")

Attaching package: ‘lubridate’

The following object is masked from ‘package:base’:

    date
dfw <- read_csv("WalmartSales.csv")
Parsed with column specification:
cols(
  Store = col_double(),
  Date = col_date(format = ""),
  IsHoliday = col_logical(),
  Temperature = col_double(),
  Fuel_Price = col_double(),
  CPI = col_double(),
  Unemployment = col_double(),
  Size = col_double(),
  Weekly_Sales = col_double()
)
dfw
summary(dfw)
     Store         Date            IsHoliday        Temperature       Fuel_Price         CPI         Unemployment   
 Min.   : 1   Min.   :2010-02-05   Mode :logical   Min.   : -2.06   Min.   :2.472   Min.   :126.1   Min.   : 3.879  
 1st Qu.:12   1st Qu.:2010-10-08   FALSE:5985      1st Qu.: 47.46   1st Qu.:2.933   1st Qu.:131.7   1st Qu.: 6.891  
 Median :23   Median :2011-06-17   TRUE :450       Median : 62.67   Median :3.445   Median :182.6   Median : 7.874  
 Mean   :23   Mean   :2011-06-17                   Mean   : 60.66   Mean   :3.359   Mean   :171.6   Mean   : 7.999  
 3rd Qu.:34   3rd Qu.:2012-02-24                   3rd Qu.: 74.94   3rd Qu.:3.735   3rd Qu.:212.7   3rd Qu.: 8.622  
 Max.   :45   Max.   :2012-10-26                   Max.   :100.14   Max.   :4.468   Max.   :227.2   Max.   :14.313  
      Size         Weekly_Sales    
 Min.   : 34875   Min.   :  68982  
 1st Qu.: 70713   1st Qu.: 375614  
 Median :126512   Median : 639652  
 Mean   :130288   Mean   : 701560  
 3rd Qu.:202307   3rd Qu.: 958807  
 Max.   :219622   Max.   :2773216  
fitCPI <- lm(formula = Weekly_Sales ~ CPI, data = dfw)
summary(fitCPI)

Call:
lm(formula = Weekly_Sales ~ CPI, data = dfw)

Residuals:
    Min      1Q  Median      3Q     Max 
-662386 -318443  -73868  258442 2095880 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 827280.5    21778.4  37.986  < 2e-16 ***
CPI           -732.7      123.7  -5.923 3.33e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 390600 on 6433 degrees of freedom
Multiple R-squared:  0.005423,  Adjusted R-squared:  0.005269 
F-statistic: 35.08 on 1 and 6433 DF,  p-value: 3.332e-09

plotStore10 <- dfw %>% filter(Store == 10) %>%
  ggplot(mapping = aes(x = CPI, y = Weekly_Sales)) +
    geom_point() +
  geom_smooth(method = lm)
ggplotly(plotStore10)

plotStore10

plotStore11 <- dfw %>% filter(Store == 11 ) %>%
  ggplot(mapping = aes(x = CPI, y = Weekly_Sales)) +
    geom_point() +
  geom_smooth(method = lm)
ggplotly(plotStore11)

plotStore11

plotStore12 <- dfw %>% filter(Store == 12 ) %>%
  ggplot(mapping = aes(x = CPI, y = Weekly_Sales)) +
    geom_point() +
  geom_smooth(method = lm)
ggplotly(plotStore12)

plotStore12

plotStore13 <- dfw %>% filter(Store == 13 ) %>%
  ggplot(mapping = aes(x = CPI, y = Weekly_Sales)) +
    geom_point() +
  geom_smooth(method = lm)
ggplotly(plotStore13)

plotStore13

#3. Now, filter for the year 2012 instead of a store (so, you’ll plot data from all stores in a year). For this, you will need to (install and) load the lubridate library. Check the cheat sheet for lubridate here. [ Start by copying/pasting your code from Q2 into a new chunk and reuse ]
#What do you observe? Why do you think there are almost vertical clusters of observations?
plotYear <- dfw %>% filter(year(Date)== 2012) %>%
  ggplot(mapping = aes(x = CPI, y = Weekly_Sales)) +
    geom_point() +
  geom_smooth(method = lm)
plotYear

NA
NA
#4. Now, create a plot of sales in Store 1 in the year 2010. Did you know that you can use multiple arguments in one filter function as follows: filter(argument_1, argument_2,…)?
#Compared to the earlier plots, do you notice a difference in the range of CPI? Why is it so?

 dfw %>% filter(year(Date)== 2010 & Store== 1) %>%
  ggplot(mapping = aes(x = CPI, y = Weekly_Sales)) +
    geom_point() +
  geom_smooth(method = lm)

NA
NA
#5. Build another regression model but this time include both CPI and Size as independent variables and call it fitCPISize. Compare this model with the model you built in Q1. 
#Which model is better at explaining Weekly Sales? Why? Hint: Use anova() as well.
fitCPISize <- lm(formula = Weekly_Sales ~ CPI + Size, data = dfw)
anova(fitCPISize)
Analysis of Variance Table

Response: Weekly_Sales
            Df     Sum Sq    Mean Sq   F value    Pr(>F)    
CPI          1 5.3507e+12 5.3507e+12    90.748 < 2.2e-16 ***
Size         1 6.0204e+14 6.0204e+14 10210.637 < 2.2e-16 ***
Residuals 6432 3.7924e+14 5.8962e+10                        
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
summary(fitCPISize)

Call:
lm(formula = Weekly_Sales ~ CPI + Size, data = dfw)

Residuals:
    Min      1Q  Median      3Q     Max 
-563750 -167145  -29612  112172 1912650 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  1.828e+05  1.497e+04  12.216   <2e-16 ***
CPI         -6.570e+02  7.692e+01  -8.542   <2e-16 ***
Size         4.847e+00  4.796e-02 101.048   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 242800 on 6432 degrees of freedom
Multiple R-squared:  0.6156,    Adjusted R-squared:  0.6155 
F-statistic:  5151 on 2 and 6432 DF,  p-value: < 2.2e-16
fitFull <- lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Temperature + Fuel_Price + Unemployment, data = dfw)
summary(fitFull)

Call:
lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Temperature + 
    Fuel_Price + Unemployment, data = dfw)

Residuals:
    Min      1Q  Median      3Q     Max 
-557148 -165608  -24125  112851 1918479 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)    3.133e+05  3.546e+04   8.834  < 2e-16 ***
CPI           -9.461e+02  8.445e+01 -11.203  < 2e-16 ***
Size           4.840e+00  4.802e-02 100.786  < 2e-16 ***
IsHolidayTRUE  6.012e+04  1.196e+04   5.026 5.14e-07 ***
Temperature    1.002e+03  1.739e+02   5.761 8.72e-09 ***
Fuel_Price    -1.333e+04  6.822e+03  -1.954   0.0507 .  
Unemployment  -1.252e+04  1.725e+03  -7.258 4.40e-13 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 241200 on 6428 degrees of freedom
Multiple R-squared:  0.621, Adjusted R-squared:  0.6206 
F-statistic:  1755 on 6 and 6428 DF,  p-value: < 2.2e-16
anova(fitFull)
Analysis of Variance Table

Response: Weekly_Sales
               Df     Sum Sq    Mean Sq    F value    Pr(>F)    
CPI             1 5.3507e+12 5.3507e+12    91.9780 < 2.2e-16 ***
Size            1 6.0204e+14 6.0204e+14 10348.9922 < 2.2e-16 ***
IsHoliday       1 1.0402e+12 1.0402e+12    17.8814 2.384e-05 ***
Temperature     1 1.1309e+12 1.1309e+12    19.4403 1.055e-05 ***
Fuel_Price      1 6.7442e+10 6.7442e+10     1.1593    0.2816    
Unemployment    1 3.0642e+12 3.0642e+12    52.6735 4.403e-13 ***
Residuals    6428 3.7394e+14 5.8173e+10                         
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#8. The output of Q7 shows that temperature is positively associated with weekly sales. However, is that relationship really linear? Test it out by adding a squared transformation of temperature into the model using the following I(Temperature^2) and call it fitFullTemp
#What is the coefficient of the squared term? Is it statistically significant? What does it mean? Based on this, what would you do differently if you were managing Walmart’s promotions?

fitFullTemp <- lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Fuel_Price + Temperature + Unemployment + I(Temperature^2), data = dfw)
summary(fitFullTemp)

Call:
lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Fuel_Price + 
    Temperature + Unemployment + I(Temperature^2), data = dfw)

Residuals:
    Min      1Q  Median      3Q     Max 
-561455 -165260  -24674  112058 1911166 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)       2.610e+05  4.111e+04   6.350 2.30e-10 ***
CPI              -9.547e+02  8.449e+01 -11.300  < 2e-16 ***
Size              4.831e+00  4.811e-02 100.420  < 2e-16 ***
IsHolidayTRUE     6.230e+04  1.199e+04   5.197 2.09e-07 ***
Fuel_Price       -1.471e+04  6.841e+03  -2.151   0.0315 *  
Temperature       3.294e+03  9.301e+02   3.542   0.0004 ***
Unemployment     -1.253e+04  1.724e+03  -7.268 4.09e-13 ***
I(Temperature^2) -1.982e+01  7.901e+00  -2.509   0.0121 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 241100 on 6427 degrees of freedom
Multiple R-squared:  0.6214,    Adjusted R-squared:  0.621 
F-statistic:  1507 on 7 and 6427 DF,  p-value: < 2.2e-16
dfw %>% ggplot(aes(x= Temperature, y= Weekly_Sales)) +
geom_smooth(method= lm, formula = y ~ x + I(x^2))

#dplyr::setdiff #detach(‘package:lubridate’, unload = TRUE) #When sometimes the package masks the functions we need to unload it.

set.seed(333)
dfwTrain <- dfw %>% sample_frac(0.8)
dfwTest <- dplyr::setdiff(dfw, dfwTrain)

fitOrg <- lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Fuel_Price + Temperature + Unemployment + I(Temperature^2), data = dfwTrain)
fitOrg

Call:
lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Fuel_Price + 
    Temperature + Unemployment + I(Temperature^2), data = dfwTrain)

Coefficients:
     (Intercept)               CPI              Size     IsHolidayTRUE        Fuel_Price       Temperature  
      283095.679          -994.622             4.824         57721.650        -11839.300          2614.925  
    Unemployment  I(Temperature^2)  
      -12726.699           -14.466  
rmse(resultsOrg, truth= Weekly_Sales, estimate = predictedSales)
mae(resultsOrg, truth= Weekly_Sales, estimate= predictedSales)

#fitFull <- lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Temperature + Fuel_Price + Unemployment, data = dfw)


#?rmse
performance <- metric_set(rmse, mae)
performance
function (data, truth, estimate, na_rm = TRUE, ...) 
{
    call_args <- quos(data = data, truth = !!enquo(truth), estimate = !!enquo(estimate), 
        na_rm = na_rm, ... = ...)
    calls <- lapply(fns, call2, !!!call_args)
    metric_list <- mapply(FUN = eval_safely, calls, names(calls), 
        SIMPLIFY = FALSE, USE.NAMES = FALSE)
    bind_rows(metric_list)
}
<bytecode: 0x7fc479be4138>
<environment: 0x7fc479be18e8>
attr(,"class")
[1] "numeric_metric_set" "metric_set"         "function"          
attr(,"metrics")
attr(,"metrics")$rmse
function (data, ...) 
{
    UseMethod("rmse")
}
<bytecode: 0x7fc47ef0db28>
<environment: namespace:yardstick>
attr(,"class")
[1] "numeric_metric" "function"      
attr(,"direction")
[1] "minimize"

attr(,"metrics")$mae
function (data, ...) 
{
    UseMethod("mae")
}
<bytecode: 0x7fc47eeb45f0>
<environment: namespace:yardstick>
attr(,"class")
[1] "numeric_metric" "function"      
attr(,"direction")
[1] "minimize"
performance(data= resultsOrg, truth= Weekly_Sales, estimate= predictedSales)
NA
NA
fitOrgDate <- lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Temperature + Date+ Fuel_Price + Unemployment, data = dfw)
fitOrgDate

Call:
lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Temperature + 
    Date + Fuel_Price + Unemployment, data = dfw)

Coefficients:
  (Intercept)            CPI           Size  IsHolidayTRUE    Temperature           Date     Fuel_Price  
    25029.055       -970.072          4.842      58776.597        992.061         21.388     -23991.947  
 Unemployment  
   -11924.759  
summary(fitOrgDate)

Call:
lm(formula = Weekly_Sales ~ CPI + Size + IsHoliday + Temperature + 
    Date + Fuel_Price + Unemployment, data = dfw)

Residuals:
    Min      1Q  Median      3Q     Max 
-553184 -166171  -24051  113175 1919129 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)    2.503e+04  2.469e+05   0.101   0.9192    
CPI           -9.701e+02  8.686e+01 -11.168  < 2e-16 ***
Size           4.842e+00  4.804e-02 100.773  < 2e-16 ***
IsHolidayTRUE  5.878e+04  1.202e+04   4.892 1.02e-06 ***
Temperature    9.921e+02  1.740e+02   5.700 1.25e-08 ***
Date           2.139e+01  1.813e+01   1.180   0.2381    
Fuel_Price    -2.399e+04  1.132e+04  -2.119   0.0341 *  
Unemployment  -1.192e+04  1.796e+03  -6.639 3.42e-11 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 241200 on 6427 degrees of freedom
Multiple R-squared:  0.6211,    Adjusted R-squared:  0.6207 
F-statistic:  1505 on 7 and 6427 DF,  p-value: < 2.2e-16
performance(data= resultsOrgDate, truth= Weekly_Sales, estimate= predictedSales)
NA
NA

#10.he finale has to be sweet, right? Instead of using sales, create a log-transformed version, set the seed, split the data, run the model fitLog, make predictions, calculate performance. #Have the coefficient estimates and variance explained in DV improved? Compare the model output and performance of fitLog with that of fitOrg from Q9c, and discuss. #Check and compare the diagnostics from fitLog with those from fitOrg, and discuss.

set.seed(333)
dfwTrainLog <- dfw %>% sample_frac(0.8)
dfwTestLog <- dplyr::setdiff(dfw, dfwTrainLog)

fitLog <- lm(formula = log(Weekly_Sales) ~ CPI + Size + IsHoliday + Temperature + Fuel_Price + Unemployment, data = dfwTrain)
fitLog

Call:
lm(formula = log(Weekly_Sales) ~ CPI + Size + IsHoliday + Temperature + 
    Fuel_Price + Unemployment, data = dfwTrain)

Coefficients:
  (Intercept)            CPI           Size  IsHolidayTRUE    Temperature     Fuel_Price   Unemployment  
    1.248e+01     -1.261e-03      8.087e-06      6.265e-02      2.839e-04      3.395e-03     -7.354e-03  
summary(fitLog)

Call:
lm(formula = log(Weekly_Sales) ~ CPI + Size + IsHoliday + Temperature + 
    Fuel_Price + Unemployment, data = dfwTrain)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.48085 -0.22739 -0.02379  0.22753  1.47557 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)    1.248e+01  5.497e-02 227.067  < 2e-16 ***
CPI           -1.261e-03  1.301e-04  -9.691  < 2e-16 ***
Size           8.087e-06  7.407e-08 109.172  < 2e-16 ***
IsHolidayTRUE  6.265e-02  1.843e-02   3.399 0.000681 ***
Temperature    2.839e-04  2.688e-04   1.056 0.290878    
Fuel_Price     3.395e-03  1.055e-02   0.322 0.747646    
Unemployment  -7.354e-03  2.677e-03  -2.747 0.006040 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3339 on 5141 degrees of freedom
Multiple R-squared:  0.7054,    Adjusted R-squared:  0.7051 
F-statistic:  2052 on 6 and 5141 DF,  p-value: < 2.2e-16

#Bonus question: Instead of predicting sales, you may also want to create a new dependent variable by dividing the Weekly Sales by store Size (“Sales per square foot” -makes sense if you focus on the utilization of store space, for example). Call it fitSalesSqFoot. For this exercise, like in Q10, create a variable, set the seed, split the data, make predictions, calculate performance. What do you think is going on here? Discuss. In addition, in this model, you may want to try removing the variable Size, because your DV is a function of it now. Explore the differences.


dfw1 <- dfw %>% mutate(SalesSqFoot = Weekly_Sales/Size)
dfw1

set.seed(333)
dfwTrain1 <- dfw1 %>% sample_frac(0.8)
dfwTest1 <- dplyr::setdiff(dfw1, dfwTrain1)
fitSqFoot <- lm(formula = SalesSqFoot ~ CPI + IsHoliday + Temperature + Unemployment+ Fuel_Price, data = dfw1)
fitSqFoot
summary(fitSqFoot)
resultsSqFoot <-dfwTest1 %>%
            mutate(predictedSales = predict(fitSqFoot, dfwTest1))
resultsSqFoot
performance(data=resultsSqFoot, truth= SalesSqFoot, estimate= predictedSales)
LS0tCnRpdGxlOiAiTGFiIDEgLSBQYXJ0IEIiCm91dHB1dDoKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OgogICAgbGF0ZXhfZW5naW5lOiB4ZWxhdGV4CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAphbHdheXNfYWxsb3dfaHRtbDogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgojIFRoaXMgY2h1bmsgc2hvd3MvaGlkZXMgdGhlIGNvZGUgaW4geW91ciBmaW5hbCByZXBvcnQuIFdoZW4gZWNobyA9IFRSVUUsIHRoZSBjb2RlCiMgaXMgc2hvd24gaW4gdGhlIHJlcG9ydC4gV2hlbiBlY2hvID0gRkFMU0UsIHRoZSBjb2RlIGlzIGhpZGRlbiBmcm9tIHRoZSBmaW5hbCByZXBvcnQuCiMgV2Ugd291bGQgbGlrZSB0byBzZWUgeW91ciBjb2RlLCBzbyBwbGVhc2UgbGVhdmUgdGhlIHNldHRpbmcgYXMgaXMgZHVyaW5nIHRoZSBjb3Vyc2UuCiMgVGhpcyBjaHVuayB3aWxsIG5vdCBzaG93IHVwIGluIHlvdXIgcmVwb3J0cywgc28geW91IGNhbiBzYWZlbHkgaWdub3JlIGl0cyBleGlzdGVuY2UuCgprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgpgYGAKClRoZSBmb2xsb3dpbmcgaXMgeW91ciBmaXJzdCBjaHVuayB0byBzdGFydCB3aXRoLiBSZW1lbWJlciwgeW91IGNhbiBhZGQgY2h1bmtzIHVzaW5nIHRoZSBtZW51CmFib3ZlIChJbnNlcnQgLT4gUikgb3IgdXNpbmcgdGhlIGtleWJvYXJkIHNob3J0Y3V0IEN0cmwrQWx0K0kuIEEgZ29vZCBwcmFjdGljZSBpcyB0byB1c2UKZGlmZmVyZW50IGNvZGUgY2h1bmtzIHRvIGFuc3dlciBkaWZmZXJlbnQgcXVlc3Rpb25zLiBZb3UgY2FuIGRlbGV0ZSB0aGlzIGNvbW1lbnQgaWYgeW91IGxpa2UuCgpPdGhlciB1c2VmdWwga2V5Ym9hcmQgc2hvcnRjdXRzIGluY2x1ZGUgQWx0LSBmb3IgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IsIGFuZCBDdHJsK1NoaWZ0K00KZm9yIHRoZSBwaXBlIG9wZXJhdG9yLiBZb3UgY2FuIGRlbGV0ZSB0aGVzZSByZW1pbmRlcnMgaWYgeW91IGRvbid0IHdhbnQgdGhlbSBpbiB5b3VyIHJlcG9ydC4KCmBgYHtyfQoKI3NldHdkKCJDOi8uLi4iKQoKbGlicmFyeSgidGlkeXZlcnNlIikKbGlicmFyeSgidGlkeW1vZGVscyIpCmxpYnJhcnkoInBsb3RseSIpCmxpYnJhcnkoInNraW1yIikKI2luc3RhbGwucGFja2FnZXMoIkNBUlMiKQojaW5zdGFsbC5wYWNrYWdlcygibHVicmlkYXRlIikKbGlicmFyeSgiQ0FSUyIpCmxpYnJhcnkoImx1YnJpZGF0ZSIpCgoKCmBgYAoKYGBge3J9CmRmdyA8LSByZWFkX2NzdigiV2FsbWFydFNhbGVzLmNzdiIpCmRmdwpgYGAKYGBge3J9CnN1bW1hcnkoZGZ3KQpgYGAKYGBge3J9CiMgUTEuIENyZWF0ZSBhIHJlZ3Jlc3Npb24gbW9kZWwgdXNpbmcgV2Vla2x5X1NhbGVzIGFzIHRoZSBEViAoRGVwZW5kZW50IFZhcmlhYmxlLCBvdXRjb21lIHZhcmlhYmxlKSwgYW5kIENQSSBhcyB0aGUgSVYgKEluZGVwZW5kZW50IFZhcmlhYmxlLCBmZWF0dXJlLCBwcmVkaWN0b3IsIGV4cGxhbmF0b3J5IHZhcmlhYmxlKS4KCmZpdENQSSA8LSBsbShmb3JtdWxhID0gV2Vla2x5X1NhbGVzIH4gQ1BJLCBkYXRhID0gZGZ3KQpzdW1tYXJ5KGZpdENQSSkKCmBgYApgYGB7cn0KIyBRMi4gRm9yIFN0b3JlIDEwLCBjcmVhdGUgYSBzY2F0dGVyIHBsb3Qgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENQSSBhbmQgV2Vla2x5X1NhbGVzLiBBZGQgYSByZWdyZXNzaW9uIGxpbmUgdG8gdGhpcyBwbG90LiBXaGF0IGRvIHlvdSBvYnNlcnZlPyBEb2VzIGl0IGFsaWduIHdpdGggeW91ciBpbnRlcnByZXRhdGlvbiBpbiBRMT8gTm93LCB0cnkgaXQgZm9yIFN0b3JlIDExLCBTdG9yZSAxMiwgYW5kIFN0b3JlIDEzLiBXaGF0IGRvIHlvdSB0aGluayBpcyBnb2luZyBvbiBoZXJlPwoKcGxvdFN0b3JlMTAgPC0gZGZ3ICU+JSBmaWx0ZXIoU3RvcmUgPT0gMTApICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBDUEksIHkgPSBXZWVrbHlfU2FsZXMpKSArCiAgICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtKQpnZ3Bsb3RseShwbG90U3RvcmUxMCkKcGxvdFN0b3JlMTAKYGBgCmBgYHtyfQpwbG90U3RvcmUxMSA8LSBkZncgJT4lIGZpbHRlcihTdG9yZSA9PSAxMSApICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBDUEksIHkgPSBXZWVrbHlfU2FsZXMpKSArCiAgICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtKQpnZ3Bsb3RseShwbG90U3RvcmUxMSkKcGxvdFN0b3JlMTEKCmBgYApgYGB7cn0KcGxvdFN0b3JlMTIgPC0gZGZ3ICU+JSBmaWx0ZXIoU3RvcmUgPT0gMTIgKSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gQ1BJLCB5ID0gV2Vla2x5X1NhbGVzKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSkKZ2dwbG90bHkocGxvdFN0b3JlMTIpCnBsb3RTdG9yZTEyCmBgYAoKYGBge3J9CnBsb3RTdG9yZTEzIDwtIGRmdyAlPiUgZmlsdGVyKFN0b3JlID09IDEzICkgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IENQSSwgeSA9IFdlZWtseV9TYWxlcykpICsKICAgIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0pCmdncGxvdGx5KHBsb3RTdG9yZTEzKQpwbG90U3RvcmUxMwpgYGAKCmBgYHtyfQojMy4gTm93LCBmaWx0ZXIgZm9yIHRoZSB5ZWFyIDIwMTIgaW5zdGVhZCBvZiBhIHN0b3JlIChzbywgeW914oCZbGwgcGxvdCBkYXRhIGZyb20gYWxsIHN0b3JlcyBpbiBhIHllYXIpLiBGb3IgdGhpcywgeW91IHdpbGwgbmVlZCB0byAoaW5zdGFsbCBhbmQpIGxvYWQgdGhlIGx1YnJpZGF0ZSBsaWJyYXJ5LiBDaGVjayB0aGUgY2hlYXQgc2hlZXQgZm9yIGx1YnJpZGF0ZSBoZXJlLiBbIFN0YXJ0IGJ5IGNvcHlpbmcvcGFzdGluZyB5b3VyIGNvZGUgZnJvbSBRMiBpbnRvIGEgbmV3IGNodW5rIGFuZCByZXVzZSBdCiNXaGF0IGRvIHlvdSBvYnNlcnZlPyBXaHkgZG8geW91IHRoaW5rIHRoZXJlIGFyZSBhbG1vc3QgdmVydGljYWwgY2x1c3RlcnMgb2Ygb2JzZXJ2YXRpb25zPwpwbG90WWVhciA8LSBkZncgJT4lIGZpbHRlcih5ZWFyKERhdGUpPT0gMjAxMikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IENQSSwgeSA9IFdlZWtseV9TYWxlcykpICsKICAgIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0pCnBsb3RZZWFyCgoKYGBgCmBgYHtyfQojNC4gTm93LCBjcmVhdGUgYSBwbG90IG9mIHNhbGVzIGluIFN0b3JlIDEgaW4gdGhlIHllYXIgMjAxMC4gRGlkIHlvdSBrbm93IHRoYXQgeW91IGNhbiB1c2UgbXVsdGlwbGUgYXJndW1lbnRzIGluIG9uZSBmaWx0ZXIgZnVuY3Rpb24gYXMgZm9sbG93czogZmlsdGVyKGFyZ3VtZW50XzEsIGFyZ3VtZW50XzIs4oCmKT8KI0NvbXBhcmVkIHRvIHRoZSBlYXJsaWVyIHBsb3RzLCBkbyB5b3Ugbm90aWNlIGEgZGlmZmVyZW5jZSBpbiB0aGUgcmFuZ2Ugb2YgQ1BJPyBXaHkgaXMgaXQgc28/CgogZGZ3ICU+JSBmaWx0ZXIoeWVhcihEYXRlKT09IDIwMTAgJiBTdG9yZT09IDEpICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBDUEksIHkgPSBXZWVrbHlfU2FsZXMpKSArCiAgICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtKQoKCmBgYApgYGB7cn0KIzUuIEJ1aWxkIGFub3RoZXIgcmVncmVzc2lvbiBtb2RlbCBidXQgdGhpcyB0aW1lIGluY2x1ZGUgYm90aCBDUEkgYW5kIFNpemUgYXMgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFuZCBjYWxsIGl0IGZpdENQSVNpemUuIENvbXBhcmUgdGhpcyBtb2RlbCB3aXRoIHRoZSBtb2RlbCB5b3UgYnVpbHQgaW4gUTEuIAojV2hpY2ggbW9kZWwgaXMgYmV0dGVyIGF0IGV4cGxhaW5pbmcgV2Vla2x5IFNhbGVzPyBXaHk/IEhpbnQ6IFVzZSBhbm92YSgpIGFzIHdlbGwuCmZpdENQSVNpemUgPC0gbG0oZm9ybXVsYSA9IFdlZWtseV9TYWxlcyB+IENQSSArIFNpemUsIGRhdGEgPSBkZncpCmFub3ZhKGZpdENQSVNpemUpCnN1bW1hcnkoZml0Q1BJU2l6ZSkKCmBgYApgYGB7cn0KIzcuIExldOKAmXMgYnVpbGQgYSBmdWxsIG1vZGVsIG5vdyBhbmQgY2FsbCBpdCBmaXRGdWxsLiBUaGlzIHRpbWUsIGluY2x1ZGUgYWxsIHRoZSB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQgKEVYQ0VQVCBTdG9yZSBBTkQgRGF0ZSkgYW5kIHJlcG9ydCB5b3VyIG9ic2VydmF0aW9ucy4gWW91IGNhbiBhbHNvIHVzZSBhbm92YSgpIHRvIGNvbXBhcmUgdGhlIHJlZHVjZWQgbW9kZWwgaW4gUTUgd2l0aCB0aGUgZnVsbCBtb2RlbCB5b3UgaGF2ZSBqdXN0IGJ1aWx0IGluIHRoaXMgcXVlc3Rpb24uCgpmaXRGdWxsIDwtIGxtKGZvcm11bGEgPSBXZWVrbHlfU2FsZXMgfiBDUEkgKyBTaXplICsgSXNIb2xpZGF5ICsgVGVtcGVyYXR1cmUgKyBGdWVsX1ByaWNlICsgVW5lbXBsb3ltZW50LCBkYXRhID0gZGZ3KQpzdW1tYXJ5KGZpdEZ1bGwpCmFub3ZhKGZpdEZ1bGwpCmBgYAoKYGBge3J9CiM4LiBUaGUgb3V0cHV0IG9mIFE3IHNob3dzIHRoYXQgdGVtcGVyYXR1cmUgaXMgcG9zaXRpdmVseSBhc3NvY2lhdGVkIHdpdGggd2Vla2x5IHNhbGVzLiBIb3dldmVyLCBpcyB0aGF0IHJlbGF0aW9uc2hpcCByZWFsbHkgbGluZWFyPyBUZXN0IGl0IG91dCBieSBhZGRpbmcgYSBzcXVhcmVkIHRyYW5zZm9ybWF0aW9uIG9mIHRlbXBlcmF0dXJlIGludG8gdGhlIG1vZGVsIHVzaW5nIHRoZSBmb2xsb3dpbmcgSShUZW1wZXJhdHVyZV4yKSBhbmQgY2FsbCBpdCBmaXRGdWxsVGVtcAojV2hhdCBpcyB0aGUgY29lZmZpY2llbnQgb2YgdGhlIHNxdWFyZWQgdGVybT8gSXMgaXQgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudD8gV2hhdCBkb2VzIGl0IG1lYW4/IEJhc2VkIG9uIHRoaXMsIHdoYXQgd291bGQgeW91IGRvIGRpZmZlcmVudGx5IGlmIHlvdSB3ZXJlIG1hbmFnaW5nIFdhbG1hcnTigJlzIHByb21vdGlvbnM/CgpmaXRGdWxsVGVtcCA8LSBsbShmb3JtdWxhID0gV2Vla2x5X1NhbGVzIH4gQ1BJICsgU2l6ZSArIElzSG9saWRheSArIEZ1ZWxfUHJpY2UgKyBUZW1wZXJhdHVyZSArIFVuZW1wbG95bWVudCArIEkoVGVtcGVyYXR1cmVeMiksIGRhdGEgPSBkZncpCnN1bW1hcnkoZml0RnVsbFRlbXApCgoKCmBgYApgYGB7cn0KZGZ3ICU+JSBnZ3Bsb3QoYWVzKHg9IFRlbXBlcmF0dXJlLCB5PSBXZWVrbHlfU2FsZXMpKSArCmdlb21fc21vb3RoKG1ldGhvZD0gbG0sIGZvcm11bGEgPSB5IH4geCArIEkoeF4yKSkKCmBgYAoKI2RwbHlyOjpzZXRkaWZmCiNkZXRhY2goJ3BhY2thZ2U6bHVicmlkYXRlJywgdW5sb2FkID0gVFJVRSkgCiNXaGVuIHNvbWV0aW1lcyB0aGUgcGFja2FnZSBtYXNrcyB0aGUgZnVuY3Rpb25zIHdlIG5lZWQgdG8gdW5sb2FkIGl0LiAKCgpgYGB7cn0KIzkuIEluIGEgdHJ1ZSBwcmVkaWN0aXZlIGFuYWx5dGljcyBleGVyY2lzZSwgd2UgbmVlZCB0byBzcGxpdCB0aGUgZGF0YXNldCwgdHJhaW4gdGhlIG1vZGVsIHVzaW5nIHRoZSB0cmFpbmluZyBkYXRhc2V0IGFuZCBtYWtlIHByZWRpY3Rpb25zIHVzaW5nIHRoZSB0ZXN0IHNldC4gTm93LCBsZXTigJlzIGRvIGl0IHRoZSBwcmVkaWN0aXZlIHdheS4gCgpzZXQuc2VlZCgzMzMpCmRmd1RyYWluIDwtIGRmdyAlPiUgc2FtcGxlX2ZyYWMoMC44KQpkZndUZXN0IDwtIGRwbHlyOjpzZXRkaWZmKGRmdywgZGZ3VHJhaW4pCgpmaXRPcmcgPC0gbG0oZm9ybXVsYSA9IFdlZWtseV9TYWxlcyB+IENQSSArIFNpemUgKyBJc0hvbGlkYXkgKyBGdWVsX1ByaWNlICsgVGVtcGVyYXR1cmUgKyBVbmVtcGxveW1lbnQgKyBJKFRlbXBlcmF0dXJlXjIpLCBkYXRhID0gZGZ3VHJhaW4pCmZpdE9yZwoKCgoKCmBgYApgYGB7cn0KdGlkeShmaXRPcmcpICAgICAgICAgCmBgYAoKYGBge3J9CnJlc3VsdHNPcmcgPC0gZGZ3VGVzdCAlPiUKICAJCQltdXRhdGUocHJlZGljdGVkU2FsZXMgPSBwcmVkaWN0KGZpdE9yZywgZGZ3VGVzdCkpCnJlc3VsdHNPcmcKCmBgYApgYGB7cn0Kcm1zZShyZXN1bHRzT3JnLCB0cnV0aD0gV2Vla2x5X1NhbGVzLCBlc3RpbWF0ZSA9IHByZWRpY3RlZFNhbGVzKQptYWUocmVzdWx0c09yZywgdHJ1dGg9IFdlZWtseV9TYWxlcywgZXN0aW1hdGU9IHByZWRpY3RlZFNhbGVzKQoKI2ZpdEZ1bGwgPC0gbG0oZm9ybXVsYSA9IFdlZWtseV9TYWxlcyB+IENQSSArIFNpemUgKyBJc0hvbGlkYXkgKyBUZW1wZXJhdHVyZSArIEZ1ZWxfUHJpY2UgKyBVbmVtcGxveW1lbnQsIGRhdGEgPSBkZncpCgoKIz9ybXNlCnBlcmZvcm1hbmNlIDwtIG1ldHJpY19zZXQocm1zZSwgbWFlKQpwZXJmb3JtYW5jZQoKcGVyZm9ybWFuY2UoZGF0YT0gcmVzdWx0c09yZywgdHJ1dGg9IFdlZWtseV9TYWxlcywgZXN0aW1hdGU9IHByZWRpY3RlZFNhbGVzKQoKCmBgYApgYGB7cn0KCmZpdE9yZ0RhdGUgPC0gbG0oZm9ybXVsYSA9IFdlZWtseV9TYWxlcyB+IENQSSArIFNpemUgKyBJc0hvbGlkYXkgKyBUZW1wZXJhdHVyZSArIERhdGUrIEZ1ZWxfUHJpY2UgKyBVbmVtcGxveW1lbnQsIGRhdGEgPSBkZncpCmZpdE9yZ0RhdGUKc3VtbWFyeShmaXRPcmdEYXRlKQoKCgoKCgpgYGAKYGBge3J9CnJlc3VsdHNPcmdEYXRlIDwtZGZ3VGVzdCAlPiUKICAJCQltdXRhdGUocHJlZGljdGVkU2FsZXMgPSBwcmVkaWN0KGZpdE9yZ0RhdGUsIGRmd1Rlc3QpKQpyZXN1bHRzT3JnRGF0ZQpgYGAKCmBgYHtyfQpwZXJmb3JtYW5jZShkYXRhPSByZXN1bHRzT3JnRGF0ZSwgdHJ1dGg9IFdlZWtseV9TYWxlcywgZXN0aW1hdGU9IHByZWRpY3RlZFNhbGVzKQoKCmBgYAoKYGBge3J9CmZpdE9yZ05vVW4gPC0gbG0oZm9ybXVsYSA9IFdlZWtseV9TYWxlcyB+IENQSSArIFNpemUgKyBJc0hvbGlkYXkgKyBUZW1wZXJhdHVyZSArIEZ1ZWxfUHJpY2UsIGRhdGEgPSBkZncpCgpyZXN1bHRzT3JnTm9VbiA8LWRmd1Rlc3QgJT4lCiAgCQkJbXV0YXRlKHByZWRpY3RlZFNhbGVzID0gcHJlZGljdChmaXRPcmdOb1VuLCBkZndUZXN0KSkKcmVzdWx0c09yZ05vVW4KCgoKYGBgCmBgYHtyfQpwZXJmb3JtYW5jZShkYXRhPSByZXN1bHRzT3JnTm9VbiwgdHJ1dGg9IFdlZWtseV9TYWxlcywgZXN0aW1hdGU9IHByZWRpY3RlZFNhbGVzKQpgYGAKCgojMTAuaGUgZmluYWxlIGhhcyB0byBiZSBzd2VldCwgcmlnaHQ/IEluc3RlYWQgb2YgdXNpbmcgc2FsZXMsIGNyZWF0ZSBhIGxvZy10cmFuc2Zvcm1lZCB2ZXJzaW9uLCBzZXQgdGhlIHNlZWQsIHNwbGl0IHRoZSBkYXRhLCBydW4gdGhlIG1vZGVsIGZpdExvZywgbWFrZSBwcmVkaWN0aW9ucywgY2FsY3VsYXRlIHBlcmZvcm1hbmNlLgojSGF2ZSB0aGUgY29lZmZpY2llbnQgZXN0aW1hdGVzIGFuZCB2YXJpYW5jZSBleHBsYWluZWQgaW4gRFYgaW1wcm92ZWQ/IENvbXBhcmUgdGhlIG1vZGVsIG91dHB1dCBhbmQgcGVyZm9ybWFuY2Ugb2YgZml0TG9nIHdpdGggdGhhdCBvZiAgZml0T3JnIGZyb20gUTljLCBhbmQgZGlzY3Vzcy4KI0NoZWNrIGFuZCBjb21wYXJlIHRoZSBkaWFnbm9zdGljcyBmcm9tIGZpdExvZyB3aXRoIHRob3NlIGZyb20gZml0T3JnLCBhbmQgZGlzY3Vzcy4KCmBgYHtyfQoKc2V0LnNlZWQoMzMzKQpkZndUcmFpbkxvZyA8LSBkZncgJT4lIHNhbXBsZV9mcmFjKDAuOCkKZGZ3VGVzdExvZyA8LSBkcGx5cjo6c2V0ZGlmZihkZncsIGRmd1RyYWluTG9nKQoKZml0TG9nIDwtIGxtKGZvcm11bGEgPSBsb2coV2Vla2x5X1NhbGVzKSB+IENQSSArIFNpemUgKyBJc0hvbGlkYXkgKyBUZW1wZXJhdHVyZSArIEZ1ZWxfUHJpY2UgKyBVbmVtcGxveW1lbnQsIGRhdGEgPSBkZndUcmFpbikKZml0TG9nCnN1bW1hcnkoZml0TG9nKQoKCgpgYGAKYGBge3J9CnJlc3VsdHNMb2cgPC1kZndUZXN0TG9nICU+JQogIAkJCW11dGF0ZShwcmVkaWN0ZWRTYWxlcyA9IHByZWRpY3QoZml0TG9nLCBkZndUZXN0TG9nKSkgIApyZXN1bHRzTG9nCgoKYGBgCgpgYGB7cn0KcGVyZm9ybWFuY2UoZGF0YT1yZXN1bHRzTG9nLCB0cnV0aD0gV2Vla2x5X1NhbGVzLCBlc3RpbWF0ZT0gcHJlZGljdGVkU2FsZXMpCgoKCmBgYApgYGB7cn0KcGxvdChmaXRMb2cpCmBgYApgYGB7cn0KcGxvdChmaXRPcmcpCmBgYAoKYGBge3J9CmRmdyAlPiUgbW9kZWxyOjphZGRfcmVzaWR1YWxzKGZpdE9yZywgdmFyPSJyZXNpZCIpICU+JSAKICBnZ3Bsb3QoYWVzKERhdGUsIHJlc2lkKSkgKyBnZW9tX2xpbmUoKQpgYGAKCmBgYHtyfQpkZncgJT4lIG1vZGVscjo6YWRkX3Jlc2lkdWFscyhmaXRMb2csIHZhcj0icmVzaWQiKSAlPiUgCiAgZ2dwbG90KGFlcyhEYXRlLCByZXNpZCkpICsgZ2VvbV9saW5lKCkKYGBgCgojQm9udXMgcXVlc3Rpb246IEluc3RlYWQgb2YgcHJlZGljdGluZyBzYWxlcywgeW91IG1heSBhbHNvIHdhbnQgdG8gY3JlYXRlIGEgbmV3IGRlcGVuZGVudCB2YXJpYWJsZSBieSBkaXZpZGluZyB0aGUgV2Vla2x5IFNhbGVzIGJ5IHN0b3JlIFNpemUgKOKAnFNhbGVzIHBlciBzcXVhcmUgZm9vdOKAnSAtbWFrZXMgc2Vuc2UgaWYgeW91IGZvY3VzIG9uIHRoZSB1dGlsaXphdGlvbiBvZiBzdG9yZSBzcGFjZSwgZm9yIGV4YW1wbGUpLiBDYWxsIGl0IGZpdFNhbGVzU3FGb290LiBGb3IgdGhpcyBleGVyY2lzZSwgbGlrZSBpbiBRMTAsIGNyZWF0ZSBhIHZhcmlhYmxlLCBzZXQgdGhlIHNlZWQsIHNwbGl0IHRoZSBkYXRhLCBtYWtlIHByZWRpY3Rpb25zLCBjYWxjdWxhdGUgcGVyZm9ybWFuY2UuIFdoYXQgZG8geW91IHRoaW5rIGlzIGdvaW5nIG9uIGhlcmU/IERpc2N1c3MuIEluIGFkZGl0aW9uLCBpbiB0aGlzIG1vZGVsLCB5b3UgbWF5IHdhbnQgdG8gdHJ5IHJlbW92aW5nIHRoZSB2YXJpYWJsZSBTaXplLCBiZWNhdXNlIHlvdXIgRFYgaXMgYSBmdW5jdGlvbiBvZiBpdCBub3cuIEV4cGxvcmUgdGhlIGRpZmZlcmVuY2VzLiAKYGBge3J9CgpkZncxIDwtIGRmdyAlPiUgbXV0YXRlKFNhbGVzU3FGb290ID0gV2Vla2x5X1NhbGVzL1NpemUpCmRmdzEKCnNldC5zZWVkKDMzMykKZGZ3VHJhaW4xIDwtIGRmdzEgJT4lIHNhbXBsZV9mcmFjKDAuOCkKZGZ3VGVzdDEgPC0gZHBseXI6OnNldGRpZmYoZGZ3MSwgZGZ3VHJhaW4xKQoKCgoKCgoKCmBgYApgYGB7cn0KZml0U3FGb290IDwtIGxtKGZvcm11bGEgPSBTYWxlc1NxRm9vdCB+IENQSSArIElzSG9saWRheSArIFRlbXBlcmF0dXJlICsgVW5lbXBsb3ltZW50KyBGdWVsX1ByaWNlLCBkYXRhID0gZGZ3MSkKZml0U3FGb290CnN1bW1hcnkoZml0U3FGb290KQpgYGAKYGBge3J9CnJlc3VsdHNTcUZvb3QgPC1kZndUZXN0MSAlPiUKICAJCQltdXRhdGUocHJlZGljdGVkU2FsZXMgPSBwcmVkaWN0KGZpdFNxRm9vdCwgZGZ3VGVzdDEpKQpyZXN1bHRzU3FGb290CmBgYAoKYGBge3J9CnBlcmZvcm1hbmNlKGRhdGE9cmVzdWx0c1NxRm9vdCwgdHJ1dGg9IFNhbGVzU3FGb290LCBlc3RpbWF0ZT0gcHJlZGljdGVkU2FsZXMpCgpgYGAKCg==